package show.me.the.money.config.reportSchema.define;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.dao.DataAccessException;

import show.me.the.money.config.reportSchema.ReportDefine;
import show.me.the.money.config.reportSchema.ReportDefineFactory;
import show.me.the.money.config.schema.SchemaItem;
import show.me.the.money.util.context.Context;

@SuppressWarnings({"unchecked"})
public class ReportSchemaSum extends ReportSchema {
	private static Log logger = LogFactory.getLog(ReportSchemaSum.class);

	public ReportSchemaSum(Document doc) {
		Element root = doc.getRootElement();
		id = root.attributeValue("id", "");
		title = root.attributeValue("title", "");

		Element cnd = root.element("condition");
		if (cnd != null) {
			try {
				if(cnds == null){
					cnds = jsonMapper.readValue(cnd.getText(),List.class);
				}
				else{
					if(cnds.get(0).equals("and")){
						cnds.add(jsonMapper.readValue(cnd.getText(),List.class));
					}
					else{
						List o = new ArrayList();
						o.add("and");
						o.add(cnds);
						o.add(jsonMapper.readValue(cnd.getText(),List.class));
						cnds = o;
					}
				}
			}catch (Exception e) {
				logger.error("parse reportCondition failed:", e);
			}
		}
		List<Element> els = root.selectNodes("queryArgs/arg");
		int i = 0;
		for (Element el : els) {
			SchemaItem si = new SchemaItem(el, i);
			queryArgs.add(si);
			i++;
		}

		els = root.elements("define");
		int startRenderIndex = 0;
		for (Element el : els) {
			ReportDefine define = ReportDefineFactory.createInstance(el,
					startRenderIndex);
			define.setReportSchema(this);
			define.setQueryArgs(queryArgs);
			startRenderIndex += define.getHeaderCount();
			if (cnds != null) {
				define.addCondition(cnds);
			}
			defines.add(define);
		}

		Element el = root.element("digger");
		if (el != null) {
			diggers = new HashMap<String, String>();
			els = el.elements();
			for (Element dig : els) {
				diggers.put(dig.attributeValue("match"), dig
						.attributeValue("target"));
			}
		}

		el = root.element("chart");
		if (el != null) {
			chartInfo = new HashMap<String, String>();
			chartInfo.put("template", el.attributeValue("template"));
			chartInfo.put("chartType", el.attributeValue("chartType"));
			chartInfo.put("limit", el.attributeValue("limit"));
		}
	}
	
	public List<HashMap> run(Context ctx) throws DataAccessException {
		List<HashMap> data = null;
		if (defines.size() == 1) {
			data = defines.get(0).runSingleMode(ctx);
		} else {
			HashMap<String, HashMap> container = new LinkedHashMap<String, HashMap>();
			for (ReportDefine define : defines) {
				define.runMutiMode(container, ctx);
			}
			data = new ArrayList<HashMap>();
			data.addAll(container.values());
			ctx.put("totalCount", data.size());
			ctx.put("pageSize", data.size());
			ctx.put("pageNo", 1);
		}
		
		if (data.size() > 0) {
			List<String> fields = new ArrayList<String>();
			for (ReportDefine define : defines) {
				fields.add(define.getHeaders(false).get(0).getId());
			}

			HashMap sumitem = new HashMap();
			sumitem.putAll(data.get(0));
			for (int i = 1; i < data.size(); i++) {
				HashMap ditem = data.get(i);
				for (String key : fields) {
					double sum = Double.parseDouble(sumitem.get(key)
							.toString())
							+ Double.parseDouble(ditem.get(key).toString());
					ditem.put(key, sum);
					sumitem.put(key, sum);
				}
			}
		}
		return data;
	}
	

}
